#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use lib ("./lib", "../lib");

package My::CD;
use base qw/DBIx::EntityRecord::BaseClass/;

package My::Artist;
use base qw/DBIx::EntityRecord::BaseClass/;


package test_attributes;
use base ('Test::Class');
use Test::More;
use Test::Exception;
use Data::Dumper;
use DBIx::EntityRecord;

sub test_baseclass : Test(72) {
    my $self = shift;
    can_ok( 'My::Artist', qw/_attribute new/ );

    dies_ok { My::Artist->_attribute(); } 'attrib-empty';
    dies_ok { My::Artist->_attribute(undef); } 'attrib-undef';
    lives_ok { My::Artist->_attribute('id'); } 'attrib-id';
    can_ok( 'My::Artist', qw/id/);
    
    my $o;
    lives_ok { $o = My::Artist->new; } 'new';
    ok( defined $o, 'new defined' );
    isa_ok( $o, 'My::Artist', 'new artist' );
    isa_ok( $o, 'DBIx::EntityRecord::BaseClass', 'new entity' );

    # accessor test
    is( $o->id(), undef, 'id-undef' );
    is( $o->id(undef), undef, 'id-undef' );

    is( $o->id(0), 0, 'id-0' );
    is( $o->id, 0, 'id-0' );

    is( $o->id(1), 1, 'id-1' );
    is( $o->id, 1, 'id-1' );

    is( $o->id('a'), 'a', 'id-set' );
    is( $o->id, 'a', 'id-set' );

    is_deeply( $o->id('a','b'), [ 'a', 'b' ], 'id-set' );
    is_deeply( $o->id, [ 'a', 'b' ], 'id-set' );

    is( $o->id(undef), undef, 'id-set-undef' );
    is( $o->id, undef, 'id-set-undef' );

    is_deeply( $o->id({ a => 1 }), { a => 1 }, 'id-set-hashref' );
    is_deeply( $o->id, { a => 1 }, 'id-set-hashref' );

    # redefine accessor
    dies_ok { My::Artist->_attribute('id'); } 'accessor-redefine';
    dies_ok { My::Artist->_attribute('name', 'invalid_options'); } 'attrib-name-invalid-options';
    lives_ok { My::Artist->_attribute('name', { } ); } 'attrib-name-ok-options';

    # readonly class data
    can_ok( 'My::Artist', qw/_attributes_list/);
    my %uatt = map { $_ => $_ } My::Artist->_attributes_list();
    is( $uatt{id}, 'id' );
    is( $uatt{name}, 'name' );

    # test constructor
    lives_ok { $o = My::Artist->new; } 'new-blank';
    ok( defined $o );
    isa_ok( $o, 'My::Artist' );
    is( $o->name( 'hello' ), 'hello' );
    is( $o->name, 'hello' );

    dies_ok { $o = My::Artist->new(undef); } 'new-undef';
    dies_ok { $o = My::Artist->new([]); } 'new-unknown-paramtype';

    lives_ok { $o = My::Artist->new({}); } 'new-empty-hashref';
    ok( defined $o );
    isa_ok( $o, 'My::Artist' );

    dies_ok { $o = My::Artist->new({ -id => undef }); } 'new-unknown-attrib';
    dies_ok { $o = My::Artist->new({ ':name' => undef }); } 'new-unknown-attrib';
    lives_ok { $o = My::Artist->new({ id => undef }); } 'new-ok-attrib';
    lives_ok { $o = My::Artist->new({ name => 'hello' }); } 'new-ok-attrib';

    # require OIDs for relationships
    # belongs to relationships
    my $oid_key;
    dies_ok { My::CD->_belongs_to( 'artist', 'My::Artist' ); }  'cd-belongs-to-artist-no-artistcdoid-yet';
    dies_ok { My::CD->_oid_key( 'id' ); }                       'cd-oid-no-id-yet';
    lives_ok { My::CD->_attribute( 'id' ); }                    'cd-set-attrib-id';
    ok( not defined My::CD->_oid_key );
    lives_ok { My::CD->_oid_key( 'id' ); }                      'cd-oid-ok-id';
    dies_ok { My::CD->_oid_key( 'id', undef ) }                 'cd-oid-multi';
    ok( defined My::CD->_oid_key );
    is( My::CD->_oid_key, 'id' );
    dies_ok { My::CD->_belongs_to( 'artist', 'My::Artist' ); }  'cd-belongs-to-artist-no-artistoid-yet';
    lives_ok { My::Artist->_oid_key( 'id' ); }                  'artist-set-oid';
    dies_ok { My::CD->_belongs_to( 'id', 'My::Artist' ); }      'cd-belongs-to-artist-accessor-used';
    dies_ok { My::CD->_belongs_to( '-artist', 'My::Artist' ); } 'cd-belongs-to-artist-accessor-invalid';
    dies_ok { My::CD->_belongs_to( '', 'My::Artist' ); }        'cd-belongs-to-artist-accessor-invalid';
    dies_ok { My::CD->_belongs_to( '1', 'My::Artist' ); }       'cd-belongs-to-artist-accessor-invalid';
    dies_ok { My::CD->_belongs_to( 'a-1', 'My::Artist' ); }     'cd-belongs-to-artist-accessor-invalid';
    lives_ok { My::CD->_belongs_to( 'artist', 'My::Artist' ); } 'cd-belongs-to-artist-ok';

    # check belongs_to
    can_ok( 'My::CD', 'artist' );
    lives_ok { $o = My::CD->new; } 'new-cd';
    is( $o->artist(), undef );
    dies_ok { $o->artist(undef) } 'cd-artist-undef';
    dies_ok { $o->artist(0) } 'cd-artist-0';
    dies_ok { $o->artist(1) } 'cd-artist-1';
    dies_ok { $o->artist([]) } 'cd-artist-arrayref';
    dies_ok { $o->artist({}) } 'cd-artist-hashref';
    dies_ok { $o->artist($o) } 'cd-artist-self';
    my $artist = My::Artist->new();
    lives_ok { $o->artist($artist) } 'cd-artist-ok';
    is( $o->artist, $artist );
    dies_ok { $o->artist(undef, $artist) } 'cd-artist-set-multiple';
    dies_ok { $o->artist($artist, undef) } 'cd-artist-set-multiple';
    
}


__PACKAGE__->new->runtests;
